package com.zenithmind.task.utils;

import com.zenithmind.task.enums.TaskStatus;
import com.zenithmind.task.enums.TaskPriority;
import com.zenithmind.task.pojo.entity.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 任务验证工具类
 * 遵循面向对象设计原则：
 * 1. 单一职责原则：专注于任务数据验证
 * 2. 开闭原则：通过策略模式支持验证规则扩展
 * 3. 依赖倒置原则：依赖抽象的验证接口
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Component
public class TaskValidator {

    /**
     * 验证规则接口
     */
    public interface ValidationRule {
        /**
         * 验证任务
         * 
         * @param task 任务对象
         * @return 验证结果
         */
        ValidationResult validate(Task task);

        /**
         * 获取规则名称
         * 
         * @return 规则名称
         */
        String getRuleName();
    }

    /**
     * 验证结果
     */
    public static class ValidationResult {
        private final boolean valid;
        private final String message;
        private final String field;

        public ValidationResult(boolean valid, String message, String field) {
            this.valid = valid;
            this.message = message;
            this.field = field;
        }

        public static ValidationResult success() {
            return new ValidationResult(true, null, null);
        }

        public static ValidationResult error(String message, String field) {
            return new ValidationResult(false, message, field);
        }

        public boolean isValid() {
            return valid;
        }

        public String getMessage() {
            return message;
        }

        public String getField() {
            return field;
        }
    }

    /**
     * 验证结果集合
     */
    public static class ValidationResults {
        private final List<ValidationResult> results = new ArrayList<>();

        public void add(ValidationResult result) {
            if (result != null) {
                results.add(result);
            }
        }

        public boolean isValid() {
            return results.stream().allMatch(ValidationResult::isValid);
        }

        public List<ValidationResult> getErrors() {
            return results.stream()
                         .filter(r -> !r.isValid())
                         .collect(java.util.stream.Collectors.toList());
        }

        public List<String> getErrorMessages() {
            return getErrors().stream()
                             .map(ValidationResult::getMessage)
                             .collect(java.util.stream.Collectors.toList());
        }

        public String getFirstErrorMessage() {
            return getErrors().stream()
                             .findFirst()
                             .map(ValidationResult::getMessage)
                             .orElse(null);
        }
    }

    // ==================== 具体验证规则 ====================

    /**
     * 基本字段验证规则
     */
    public static class BasicFieldValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task == null) {
                return ValidationResult.error("任务对象不能为空", "task");
            }

            if (!StringUtils.hasText(task.getTitle())) {
                return ValidationResult.error("任务标题不能为空", "title");
            }

            if (task.getTitle().length() > 200) {
                return ValidationResult.error("任务标题长度不能超过200个字符", "title");
            }

            if (task.getDescription() != null && task.getDescription().length() > 2000) {
                return ValidationResult.error("任务描述长度不能超过2000个字符", "description");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "基本字段验证";
        }
    }

    /**
     * 状态验证规则
     */
    public static class StatusValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getStatus() == null) {
                return ValidationResult.error("任务状态不能为空", "status");
            }

            TaskStatus status = TaskStatus.getByCode(task.getStatus());
            if (status == null) {
                return ValidationResult.error("无效的任务状态", "status");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "状态验证";
        }
    }

    /**
     * 优先级验证规则
     */
    public static class PriorityValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getPriority() == null) {
                return ValidationResult.error("任务优先级不能为空", "priority");
            }

            TaskPriority priority = TaskPriority.getByCode(task.getPriority());
            if (priority == null) {
                return ValidationResult.error("无效的任务优先级", "priority");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "优先级验证";
        }
    }

    /**
     * 任务类型验证规则
     */
    public static class TaskTypeValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getTaskType() == null) {
                return ValidationResult.error("任务类型不能为空", "taskType");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "任务类型验证";
        }
    }

    /**
     * 时间验证规则
     */
    public static class TimeValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            LocalDateTime now = LocalDateTime.now();

            // 验证计划时间
            if (task.getPlannedStartTime() != null && task.getPlannedEndTime() != null) {
                if (task.getPlannedStartTime().isAfter(task.getPlannedEndTime())) {
                    return ValidationResult.error("计划开始时间不能晚于计划结束时间", "plannedStartTime");
                }
            }

            // 验证实际时间
            if (task.getActualStartTime() != null && task.getActualEndTime() != null) {
                if (task.getActualStartTime().isAfter(task.getActualEndTime())) {
                    return ValidationResult.error("实际开始时间不能晚于实际结束时间", "actualStartTime");
                }
            }

            // 验证提醒时间
            if (task.getReminderTime() != null && task.getReminderTime().isBefore(now)) {
                return ValidationResult.error("提醒时间不能早于当前时间", "reminderTime");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "时间验证";
        }
    }

    /**
     * 进度验证规则
     */
    public static class ProgressValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getProgress() != null) {
                if (task.getProgress() < 0 || task.getProgress() > 100) {
                    return ValidationResult.error("任务进度必须在0-100之间", "progress");
                }

                // 如果任务已完成，进度应该是100%
                TaskStatus status = TaskStatus.getByCode(task.getStatus());
                if (status == TaskStatus.COMPLETED && task.getProgress() != 100) {
                    return ValidationResult.error("已完成的任务进度应该是100%", "progress");
                }
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "进度验证";
        }
    }

    /**
     * 工时验证规则
     */
    public static class WorkHoursValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getEstimatedHours() != null && task.getEstimatedHours().compareTo(java.math.BigDecimal.ZERO) < 0) {
                return ValidationResult.error("预估工时不能为负数", "estimatedHours");
            }

            if (task.getActualHours() != null && task.getActualHours().compareTo(java.math.BigDecimal.ZERO) < 0) {
                return ValidationResult.error("实际工时不能为负数", "actualHours");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "工时验证";
        }
    }

    /**
     * 层级验证规则
     */
    public static class HierarchyValidationRule implements ValidationRule {
        @Override
        public ValidationResult validate(Task task) {
            if (task.getLevel() != null && task.getLevel() < 0) {
                return ValidationResult.error("任务层级不能为负数", "level");
            }

            if (task.getParentId() != null && task.getParentId().equals(task.getId())) {
                return ValidationResult.error("任务不能以自己为父任务", "parentId");
            }

            return ValidationResult.success();
        }

        @Override
        public String getRuleName() {
            return "层级验证";
        }
    }

    // ==================== 验证器主要方法 ====================

    private final List<ValidationRule> rules = new ArrayList<>();

    public TaskValidator() {
        // 注册默认验证规则
        rules.add(new BasicFieldValidationRule());
        rules.add(new StatusValidationRule());
        rules.add(new PriorityValidationRule());
        rules.add(new TaskTypeValidationRule());
        rules.add(new TimeValidationRule());
        rules.add(new ProgressValidationRule());
        rules.add(new WorkHoursValidationRule());
        rules.add(new HierarchyValidationRule());
    }

    /**
     * 添加验证规则
     * 
     * @param rule 验证规则
     */
    public void addRule(ValidationRule rule) {
        if (rule != null) {
            rules.add(rule);
        }
    }

    /**
     * 移除验证规则
     * 
     * @param ruleName 规则名称
     */
    public void removeRule(String ruleName) {
        rules.removeIf(rule -> rule.getRuleName().equals(ruleName));
    }

    /**
     * 验证任务
     * 
     * @param task 任务对象
     * @return 验证结果
     */
    public ValidationResults validate(Task task) {
        ValidationResults results = new ValidationResults();

        for (ValidationRule rule : rules) {
            try {
                ValidationResult result = rule.validate(task);
                results.add(result);
            } catch (Exception e) {
                log.error("验证规则执行失败: {}", rule.getRuleName(), e);
                results.add(ValidationResult.error("验证规则执行失败: " + e.getMessage(), "system"));
            }
        }

        return results;
    }

    /**
     * 快速验证（只返回是否有效）
     * 
     * @param task 任务对象
     * @return 是否有效
     */
    public boolean isValid(Task task) {
        return validate(task).isValid();
    }

    /**
     * 验证并获取第一个错误信息
     * 
     * @param task 任务对象
     * @return 错误信息，如果验证通过则返回null
     */
    public String getFirstError(Task task) {
        return validate(task).getFirstErrorMessage();
    }

    /**
     * 验证特定字段
     * 
     * @param task 任务对象
     * @param fieldName 字段名称
     * @return 验证结果
     */
    public ValidationResults validateField(Task task, String fieldName) {
        ValidationResults results = new ValidationResults();

        for (ValidationRule rule : rules) {
            ValidationResult result = rule.validate(task);
            if (!result.isValid() && fieldName.equals(result.getField())) {
                results.add(result);
            }
        }

        return results;
    }
}
